From: Yehuda Katz Date: Mon, 7 Apr 2014 01:26:36 +0000 (-0700) Subject: Add support for reading config X-Git-Tag: archive/raspbian/0.35.0-2+rpi1~3^2^2^2^2^2^2^2~1123 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=3a15f5b78633cf6eb9de7c89050b962266f54483;p=cargo.git Add support for reading config --- diff --git a/Makefile b/Makefile index 054ee0983..6d50d154d 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,11 @@ RUSTC ?= rustc RUSTC_FLAGS ?= # Link flags to pull in dependencies -BINS = cargo-compile \ - cargo-read-manifest \ - cargo-rustc \ - cargo-verify-project +BINS = cargo \ + cargo-compile \ + cargo-read-manifest \ + cargo-rustc \ + cargo-verify-project SRC = $(shell find src -name '*.rs') diff --git a/libs/rust-toml b/libs/rust-toml index 49290aedf..a7c9ead90 160000 --- a/libs/rust-toml +++ b/libs/rust-toml @@ -1 +1 @@ -Subproject commit 49290aedf236c365c08fbc01eb70127eb5ab4a60 +Subproject commit a7c9ead90b7eb51521f3578307fe44ca8f087b9a diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs new file mode 100644 index 000000000..bfc3b1e32 --- /dev/null +++ b/src/bin/cargo.rs @@ -0,0 +1,76 @@ +extern crate cargo; +extern crate toml; +extern crate hammer; +extern crate serialize; +extern crate collections; + +use hammer::{FlagConfig,FlagConfiguration}; +use std::{os,io}; +use serialize::{Decodable,Encodable,json}; +use cargo::{CargoResult,ToCargoError,NoFlags,execute_main_without_stdin,process_executed,handle_error}; +use cargo::util::important_paths::find_project; +use cargo::util::config; + +fn main() { + execute(); +} + +#[deriving(Encodable)] +struct ProjectLocation { + root: ~str +} + +fn execute() { + let (cmd, args) = match process(os::args()) { + Ok((cmd, args)) => (cmd, args), + Err(err) => return handle_error(err) + }; + + if cmd == ~"config" { execute_main_without_stdin(config) } + else if cmd == ~"locate-project" { execute_main_without_stdin(locate_project) } +} + +fn process(mut args: ~[~str]) -> CargoResult<(~str, ~[~str])> { + args = args.tail().to_owned(); + let head = try!(args.head().to_cargo_error(~"No subcommand found", 1)).to_owned(); + let tail = args.tail().to_owned(); + + Ok((head, tail)) +} + +#[deriving(Decodable)] +struct ConfigFlags { + key: ~str, + value: Option<~str>, + human: bool +} + +impl FlagConfig for ConfigFlags { + fn config(_: Option, c: FlagConfiguration) -> FlagConfiguration { + c.short("human", 'h') + } +} + +#[deriving(Encodable)] +struct ConfigOut { + values: collections::HashMap<~str, config::ConfigValue> +} + +fn config(args: ConfigFlags) -> CargoResult> { + let value = try!(config::get_config(os::getcwd(), args.key.as_slice())); + + if args.human { + println!("{}", value); + Ok(None) + } else { + let mut map = collections::HashMap::new(); + map.insert(args.key.clone(), value); + Ok(Some(ConfigOut { values: map })) + } +} + +fn locate_project(args: NoFlags) -> CargoResult> { + let root = try!(find_project(os::getcwd(), ~"Cargo.toml")); + let string = try!(root.as_str().to_cargo_error(format!("Your project path contains characters not representable in Unicode: {}", os::getcwd().display()), 1)); + Ok(Some(ProjectLocation { root: string.to_owned() })) +} diff --git a/src/cargo/mod.rs b/src/cargo/mod.rs index ed54f4cb6..4c9811441 100644 --- a/src/cargo/mod.rs +++ b/src/cargo/mod.rs @@ -133,12 +133,9 @@ pub fn execute_main_without_stdin<'a, T: RepresentsFlags, V: Encodable, io::IoError>>(result: CargoResult>) { +pub fn process_executed<'a, T: Encodable, io::IoError>>(result: CargoResult>) { match result { - Err(e) => { - let _ = write!(&mut std::io::stderr(), "{}", e.message); - std::os::set_exit_status(e.exit_code as int); - }, + Err(e) => handle_error(e), Ok(encodable) => { encodable.map(|encodable| { let encoded: ~str = json::Encoder::str_encode(&encodable); @@ -148,6 +145,11 @@ fn process_executed<'a, T: Encodable, io::IoError>>(result: Ca } } +pub fn handle_error(err: CargoError) { + let _ = write!(&mut std::io::stderr(), "{}", err.message); + std::os::set_exit_status(err.exit_code as int); +} + fn flags_from_args() -> CargoResult { let mut decoder = FlagDecoder::new::(std::os::args().tail()); Decodable::decode(&mut decoder).to_cargo_error(|e: HammerError| e.message, 1) diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs new file mode 100644 index 000000000..087a7b3a7 --- /dev/null +++ b/src/cargo/util/config.rs @@ -0,0 +1,58 @@ +extern crate toml; + +use super::super::{CargoResult,CargoError,ToCargoError}; +use std::{io,fmt}; + +#[deriving(Eq,Clone,Encodable,Decodable)] +pub enum Location { + Project, + Global +} + +#[deriving(Eq,Clone,Encodable,Decodable)] +pub struct ConfigValue { + value: ~str, + path: ~str +} + +impl fmt::Show for ConfigValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f.buf, "{} (from {})", self.value, self.path) + } +} + +pub fn get_config(pwd: Path, key: &str) -> CargoResult { + walk_tree(&pwd, |file| extract_config(file, key)).to_cargo_error(format!("Config key not found: {}", key), 1) +} + +pub fn set_config(key: ~str, value: ~str, location: Location) -> CargoResult<()> { + Ok(()) +} + +fn walk_tree(pwd: &Path, walk: |io::fs::File| -> CargoResult) -> Option { + let mut current = pwd.clone(); + + loop { + let possible = current.join(".cargo").join("config"); + if possible.exists() { + let res = io::fs::File::open(&possible).map(|file| walk(file)); + + match res { + Ok(Ok(res)) => return Some(res), + _ => () + } + } + + if !current.pop() { break; } + } + + None +} + +fn extract_config(file: io::fs::File, key: &str) -> CargoResult { + let path = try!(file.path().as_str().to_cargo_error(~"", 1)).to_owned(); + let mut buf = io::BufferedReader::new(file); + let root = try!(toml::parse_from_buffer(&mut buf).to_cargo_error(~"", 1)); + let val = try!(try!(root.lookup(key).to_cargo_error(~"", 1)).get_str().to_cargo_error(~"", 1)); + Ok(ConfigValue{ value: val.to_owned(), path: path }) +} diff --git a/src/cargo/util/important_paths.rs b/src/cargo/util/important_paths.rs new file mode 100644 index 000000000..231aca678 --- /dev/null +++ b/src/cargo/util/important_paths.rs @@ -0,0 +1,16 @@ +use std::os; +use super::super::{CargoResult,CargoError}; + +pub fn find_project(pwd: Path, file: ~str) -> CargoResult { + let mut current = pwd.clone(); + + loop { + if current.join(file.clone()).exists() { + return Ok(current) + } + + if !current.pop() { break; } + } + + Err(CargoError::new(format!("Could not find a Cargo manifest ({}) in your current directory or any parent directory", file), 1)) +} diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs index e4fbd2514..9bd067829 100644 --- a/src/cargo/util/mod.rs +++ b/src/cargo/util/mod.rs @@ -1,2 +1,4 @@ pub use self::process_builder::{process,ProcessBuilder}; pub mod process_builder; +pub mod config; +pub mod important_paths;